#include "xmlParse.h"



qXmlParse::qXmlParse()
{
  doc_ = nullptr;
}

qXmlParse::~qXmlParse()
{
  if(doc_)
    xmlFreeDoc(doc_);
}

char* qXmlParse::convChar(char* in, const char* fromEncode, const char* toEncode)
{
  if(!in)
    return nullptr;

  size_t size = strlen(in);
  size_t outsize = 2 * size + 1;
  char* out = new char[outsize];
  if(out)
  {
    bzero(out, outsize);
    if(fromEncode && toEncode)
    {
      iconv_t ret = iconv_open(toEncode, fromEncode);
      if((iconv_t)-1 == ret)
      {
        delete []out;
        out = nullptr;
      }
      else 
      {
        char* fromtmp = in;
        char* totmp = out;
        size_t tmpoutsize = outsize - 1;
        size_t convsize = iconv(ret, &fromtmp, &size, &totmp, &tmpoutsize);
        if(convsize == -1)
        {
          delete[] out;
          out = nullptr;
        }
        iconv_close(ret);
      }
    }
    else 
    {
      strncpy(out, in, size);
    }

  }
  return out;
}

bool qXmlParse::initFile(const char* filename)
{
  if(!filename)
  {
    LOG_ERROR("filename is null FFL[%s,%s,%d]",LOG_FFL); 
    return false;
  }

  if(doc_)
  {
    xmlFreeDoc(doc_);
    doc_ = nullptr;
  }

  doc_ = xmlParseFile(filename);
  return doc_ != nullptr;
}

xmlNodePtr qXmlParse::getRootNode()
{
  return xmlDocGetRootElement(doc_);
}

xmlNodePtr qXmlParse::getChildNode(xmlNodePtr node, const char* nodename)
{
  xmlNodePtr childNode = node->children;;
  
  if(nodename)
  {
    while(childNode)
    {
      if(!xmlStrcmp(childNode->name, (const xmlChar*)nodename))
      {
        break;
      }
      childNode = childNode->next;
    }
  }
  else 
  { 
    while(childNode)
    {
      if(!xmlNodeIsText(childNode))
      {
        break;
      }
      childNode = childNode->next;
    }
  }
  
  return childNode;
}

xmlNodePtr qXmlParse::getNextNode(xmlNodePtr node, const char* nodename)
{
  if(!node)
    return nullptr;

  xmlNodePtr nextNode = node->next;
  if(nodename)
  {
    while(nextNode)
    {
      if(!xmlStrcmp(nextNode->name,  (const xmlChar*)nodename))
        break;
      nextNode = nextNode->next;
    }
  }
  else 
  {
    while(nextNode)
    {
      if(!xmlNodeIsText(nextNode))
        break;
      nextNode = node->next;
    }
  }
  return nextNode;

}

bool qXmlParse::getNodePropNum(xmlNodePtr node, const char* propname, void* dstname, size_t dstsize)
{
  if(!node || !propname || !dstname || !dstsize)
    return false;

  char* prop = (char*)xmlGetProp(node, (const xmlChar*)propname);
  if(!prop)
    return false;

  switch(dstsize)
  {
    case sizeof(uint8):
      *(uint8*)dstname = (uint8)atoi(prop);
    case sizeof(uint16):
      *(uint16*)dstname = (uint16)atoi(prop);
    case sizeof(uint32):
      *(uint32*)dstname = atoi(prop);
    case sizeof(uint64):
      *(uint64*)dstname = atoll(prop);
    default:
      return false;
  }
  xmlFree(prop);
  return true;

}

bool qXmlParse::getNodePropStr(xmlNodePtr node, const char* propname, std::string& str)
{
  if(!node || !propname)
    return false;

  char* prop = (char*)xmlGetProp(node, (const xmlChar*)propname);
  if(!prop)
    return false;

  char* out = convChar(prop, "UTF-8", (char*)doc_->encoding);
  if(out)
  {
    str.clear();
    str = out;
    delete[] out;
  }

  xmlFree(prop);
  return true;
}
